import io
import logging, traceback, sys, threading
from common.mysql.MySQLhelper import get_sql_helper

try:
    import Queue
except ImportError:
    import queue as Queue
import requests
from ..log import set_logging
from ..utils import test_connect
from ..storage import templates
from ... import itchat

logger = logging.getLogger('itchat')

sqlhelper = get_sql_helper()

def load_register(core):
    core.auto_login = auto_login
    core.configured_reply = configured_reply
    core.msg_register = msg_register
    core.run = run


def auto_login(self, hotReload=False, statusStorageDir='itchat.pkl',
               enableCmdQR=False, picDir=None, qrCallback=None,
               loginCallback=None, exitCallback=None):
    if not test_connect():
        logger.info("You can't get access to internet or wechat domain, so exit.")
        sys.exit()
    self.useHotReload = hotReload
    self.hotReloadDir = statusStorageDir
    if hotReload:
        rval = self.load_login_status(statusStorageDir,
                                      loginCallback=loginCallback, exitCallback=exitCallback)
        if rval:
            return
        logger.error('Hot reload failed, logging in normally, error={}'.format(rval))
        self.logout()
        self.login(enableCmdQR=enableCmdQR, picDir=picDir, qrCallback=qrCallback,
                   loginCallback=loginCallback, exitCallback=exitCallback)
        self.dump_login_status(statusStorageDir)
    else:
        self.login(enableCmdQR=enableCmdQR, picDir=picDir, qrCallback=qrCallback,
                   loginCallback=loginCallback, exitCallback=exitCallback)


def configured_reply(self):
    ''' determine the type of message and reply if its method is defined
        however, I use a strange way to determine whether a msg is from massive platform
        I haven't found a better solution here
        The main problem I'm worrying about is the mismatching of new friends added on phone
        If you have any good idea, pleeeease report an issue. I will be more than grateful.
    '''
    try:
        msg = self.msgList.get(timeout=1)
    except Queue.Empty:
        pass
    else:
        if isinstance(msg['User'], templates.User):
            replyFn = self.functionDict['FriendChat'].get(msg['Type'])
        elif isinstance(msg['User'], templates.MassivePlatform):
            replyFn = self.functionDict['MpChat'].get(msg['Type'])
        elif isinstance(msg['User'], templates.Chatroom):
            replyFn = self.functionDict['GroupChat'].get(msg['Type'])
        if replyFn is None:
            r = None
        else:
            try:
                r = replyFn(msg)
                if r is not None:
                    self.send(r, msg.get('FromUserName'))
            except:
                logger.warning(traceback.format_exc())


def msg_register(self, msgType, isFriendChat=False, isGroupChat=False, isMpChat=False):
    ''' a decorator constructor
        return a specific decorator based on information given '''
    if not (isinstance(msgType, list) or isinstance(msgType, tuple)):
        msgType = [msgType]

    def _msg_register(fn):
        for _msgType in msgType:
            if isFriendChat:
                self.functionDict['FriendChat'][_msgType] = fn
            if isGroupChat:
                self.functionDict['GroupChat'][_msgType] = fn
            if isMpChat:
                self.functionDict['MpChat'][_msgType] = fn
            if not any((isFriendChat, isGroupChat, isMpChat)):
                self.functionDict['FriendChat'][_msgType] = fn
        return fn

    return _msg_register


def find_message(user_id):
    while (True):
        value = sqlhelper.fetch_all("select to_user_id, content, id, type from shequn_send_message where user_id = %s; ",
                                    (user_id))
        if value != ():
            for index in value:
                receiver = index[0]
                content = index[1]
                id = index[2]
                type = index[3]

                if (type == None):
                    type = 1
                logger.info('发送消息内容：{}, 发送人：{}， 接收人：{}'.format(content, user_id, receiver))
                try:
                    get_content(content, receiver, type)
                except:
                    logger.debug('send fail for receiver: {}'.format(receiver))
                    # 弄点失败的语句，放入数据库中
                logger.info('删除消息：{}'.format(content))
                sqlhelper.delete("DELETE from shequn_send_message where id = %s", (id))


def get_content(content, receiver, type=1):
    if type == 1:
        logger.info('开始进行消息发送：{}'.format(content))
        itchat.send(content, toUserName=receiver)
        logger.info("[WX] sendMsg={}, receiver={}".format(content, receiver))
    elif type == 3:  # 从网络下载图片
        img_url = content
        logger.debug(f"[WX] start download image, img_url={img_url}")
        pic_res = requests.get(img_url, stream=True)
        image_storage = io.BytesIO()
        size = 0
        for block in pic_res.iter_content(1024):
            size += len(block)
            image_storage.write(block)
        logger.info(f"[WX] download image success, size={size}, img_url={img_url}")
        image_storage.seek(0)
        logger.info('开始进行消息发送：{}'.format(content))
        itchat.send_image(image_storage, toUserName=receiver)
        logger.info("[WX] sendImage url={}, receiver={}".format(img_url, receiver))
    elif type == 6:  # 新增文件回复类型
        file_storage = content
        last_index = file_storage.rfind("/")
        file_storage = "/file/" + file_storage[last_index + 1:]
        logger.info("[WX] file_storage={}".format(file_storage))
        logger.info('开始进行消息发送：{}'.format(content))
        preparedFile = itchat.send_file(file_storage, toUserName=receiver)
        logger.info(preparedFile)
        logger.info("[WX] sendFile, receiver={}".format(receiver))

def run(self, debug=False, blockThread=True):
    user_id = itchat.instance.storageClass.userName
    logger.info('Start auto replying.')
    if debug:
        set_logging(loggingLevel=logging.DEBUG)

    def reply_fn():
        try:
            while self.alive:
                self.configured_reply()
        except KeyboardInterrupt:
            if self.useHotReload:
                self.dump_login_status()
            self.alive = False
            logger.debug('itchat received an ^C and exit.')
            logger.info('Bye~')

    if blockThread:
        p1 = threading.Thread(target=find_message, args=(user_id,))
        p2 = threading.Thread(target=reply_fn)

        p1.start()
        p2.start()

    else:
        replyThread = threading.Thread(target=reply_fn)
        replyThread.setDaemon(True)
        replyThread.start()